using System.Linq;
using FireStarter.Base;
using FireStarter.Base.BusinessObjectMerger;
using FireStarterModeller.BO;
using FireStarterModeller.Logic.MergeBusinessObjects;
using FireStarterModeller.Test.BO;
using NUnit.Framework;

namespace FireStarterModeller.Test.Logic.MergeBusinessObjects
{
    [TestFixture]
    public class TestMergeUIProp
    {
        [TestFixtureSetUp]
        public virtual void TestFixtureSetup()
        {
            TestUtilsLogic.SetupFixture();
        }
        [SetUp]
        public virtual void SetupTest()
        {
            TestUtilsLogic.SetupTest();
        }

        [Test]
        public void Test_MergeUIProp_WhenNoToParameters_ShouldCreateUIParameters()
        {
            //---------------Set up test pack-------------------
            var uiFieldMerger = MergeableBORegistry.Instance.Resolve<UIProp>();
            var fromUIProp = TestUtilsUIProp.GetFactory()
                .WithMany(field => field.UIParameters)
                .WithOutSingleRelationships()
                .CreateValidBusinessObject();

            var toUIProp = new UIProp();
            //---------------Assert Precondition----------------
            Assert.Greater(fromUIProp.UIParameters.Count, 2);
            Assert.AreEqual(0, toUIProp.UIParameters.Count);
            //---------------Execute Test ----------------------
            uiFieldMerger.MergeBOFrom(fromUIProp, toUIProp);
            //---------------Test Result -----------------------
            Assert.AreEqual(fromUIProp.UIParameters.Count, toUIProp.UIParameters.Count);
            Assert.AreEqual(3, toUIProp.UIParameters.Count);
        }

        [Test]
        public void Test_MergeUIProp_WhenTwoUpdatedParameters_ShouldUpdateParams()
        {
            //---------------Set up test pack-------------------
            var uiFieldMerger = MergeableBORegistry.Instance.Resolve<UIProp>();
            var fromUIProp = TestUtilsUIProp.GetFactory()
                .WithTwo(field => field.UIParameters)
                .WithOutSingleRelationships()
                .CreateValidBusinessObject();


            var toUIProp = new UIProp();
            var uiParameters = fromUIProp.UIParameters;
            var fromUIParam = uiParameters[0];
            var fromUIParam2 = uiParameters[1];
            UIParameter expectedToUIParam = AddCopiedUIParam(toUIProp, fromUIParam);
            UIParameter expectedToUIParam2 = AddCopiedUIParam(toUIProp, fromUIParam2);

            //---------------Assert Precondition----------------
            Assert.AreEqual(2, fromUIProp.UIParameters.Count);
            Assert.AreNotEqual(fromUIParam.Value, expectedToUIParam.Value);
            Assert.AreNotEqual(fromUIParam2.Value, expectedToUIParam2.Value);
            //---------------Execute Test ----------------------
            uiFieldMerger.MergeBOFrom(fromUIProp, toUIProp);
            //---------------Test Result -----------------------
            Assert.IsNotNull(toUIProp);
            Assert.AreEqual(2, toUIProp.UIParameters.Count);
            var toUIParam = toUIProp.UIParameters.First();
            //  Assert.AreSame(expectedToUIParam, toUIParam);
            Assert.AreEqual(fromUIParam.Name, toUIParam.Name);
            Assert.AreEqual(fromUIParam.Value, toUIParam.Value);
            var toUIParam2 = toUIProp.UIParameters.Last();
            //   Assert.AreSame(expectedToUIParam2, toUIParam2);
            Assert.AreEqual(fromUIParam2.Name, toUIParam2.Name);
            Assert.AreEqual(fromUIParam2.Value, toUIParam2.Value);
        }


        private static UIParameter AddCopiedUIParam(UIProp toUIProp, UIParameter fromUIParam)
        {
            var expectedToUIParam = new UIParameter {Name = fromUIParam.Name };
            toUIProp.UIParameters.Add(expectedToUIParam);
            return expectedToUIParam;
        }

        private static UIParameter CreateUIParam(UIProp  uiField)
        {
            var UIParameter = uiField.UIParameters.CreateBusinessObject();
            UIParameter.Name = TestUtilsShared.GetRandomString();
            UIParameter.Value = TestUtilsShared.GetRandomString();
            return UIParameter;
        }

        [Test]
        public void Test_MergeUIProp_WhenMergeToNotNull_ShouldUpdateUIProp()
        {
            //---------------Set up test pack-------------------
            IMergeBO<UIProp> mergeBO = MergeableBORegistry.Instance.Resolve<UIProp>();
            var fromUIProp = TestUtilsUIProp.GetFactory()
                .WithMany(field => field.UIParameters)
                .WithOutSingleRelationships()
                .CreateValidBusinessObject();
            fromUIProp.PropertyName = "SomeValue";
            var toUiField = new UIProp();
            //---------------Assert Precondition----------------
            Assert.AreNotEqual(fromUIProp.PropertyName, toUiField.PropertyName);
            //---------------Execute Test ----------------------
            mergeBO.MergeBOFrom(fromUIProp, toUiField);
            //---------------Test Result -----------------------
            Assert.AreEqual(fromUIProp.PropertyName, toUiField.PropertyName);
        }

        [Test]
        public void Test_MergeUIProp_WhenOneRemovedParameters_ShouldUpdateParamsStatusToDelete()
        {
            //---------------Set up test pack-------------------
            var uiFieldMerger = MergeableBORegistry.Instance.Resolve<UIProp>();
            var fromUIProp = new UIProp();
            var fromUIParam = CreateUIParam(fromUIProp);
            var fromUIParam2 = CreateUIParam(fromUIProp);
            var toUIProp = new UIProp();
            UIParameter expectedToUIParam = AddCopiedUIParam(toUIProp, fromUIParam);
            UIParameter expectedToUIParam2 = AddCopiedUIParam(toUIProp, fromUIParam2);
            fromUIProp.UIParameters.Remove(fromUIParam2);
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, fromUIProp.UIParameters.Count);
            Assert.AreEqual(2, toUIProp.UIParameters.Count);
            Assert.AreNotEqual(fromUIParam.Value, expectedToUIParam.Value);
            Assert.AreNotEqual(ChangeType.Update, expectedToUIParam.PendingChangeType);
            Assert.AreNotEqual(ChangeType.Delete, expectedToUIParam2.PendingChangeType);
            //---------------Execute Test ----------------------
            uiFieldMerger.MergeBOFrom(fromUIProp, toUIProp);
            //---------------Test Result -----------------------
            Assert.IsNotNull(toUIProp);
            Assert.AreEqual(2, toUIProp.UIParameters.Count);
            var toUIParam = toUIProp.UIParameters.First();
            Assert.AreSame(toUIParam, expectedToUIParam);
            var toUIParam2 = toUIProp.UIParameters.Last();
            Assert.AreSame(toUIParam2, expectedToUIParam2);
            Assert.AreEqual(ChangeType.Delete, toUIParam2.PendingChangeType);
            Assert.AreEqual(ChangeType.None, toUIParam.PendingChangeType);
        }
    }
}